{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 创建列表 Creating Lists"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "创建一个包含多个元素的列表"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['cat', 'Linus', 14, 15.6, True]\n",
      "<class 'list'>\n",
      "5\n"
     ]
    }
   ],
   "source": [
    "evens = [2, 4, 6, 8]\n",
    "pets = ['cat', 'dog', 'pig']\n",
    "# We can even mix data types within a list\n",
    "petInfo = ['cat', 'Linus', 14, 15.6, True]\n",
    "\n",
    "# Can use print and type with lists\n",
    "print(petInfo)\n",
    "print(type(petInfo))\n",
    "\n",
    "# The built-in function for length is really useful with lists\n",
    "n = len(petInfo)\n",
    "print(n)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "只有一个元素的列表"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'list'> 1 ['hello']\n",
      "<class 'list'> 1 [42]\n"
     ]
    }
   ],
   "source": [
    "a = [\"hello\"]\n",
    "b = [42]\n",
    "\n",
    "print(type(a), len(a), a)\n",
    "print(type(b), len(b), b)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "没有元素的列表（空列表）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Two standard ways to create an empty list:\n",
      "<class 'list'> 0 []\n",
      "<class 'list'> 0 []\n"
     ]
    }
   ],
   "source": [
    "print(\"Two standard ways to create an empty list:\")\n",
    "a = []\n",
    "b = list()\n",
    "\n",
    "print(type(a), len(a), a)\n",
    "print(type(b), len(b), b)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "其他创建列表的方式"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'list'> 10 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n",
      "<class 'list'> 10 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n"
     ]
    }
   ],
   "source": [
    "# Create a new list with n 0s\n",
    "n = 10\n",
    "a = [0] * n \n",
    "\n",
    "# Create a list by forcing the expansion of a range object\n",
    "b = list(range(n))\n",
    "\n",
    "print(type(a), len(a), a)\n",
    "print(type(b), len(b), b)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 列表的一些内置函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "a =  [2, 3, 5, 2]\n",
      "len = 4\n",
      "min = 2\n",
      "max = 5\n",
      "sum = 12\n"
     ]
    }
   ],
   "source": [
    "a = [2, 3, 5, 2]\n",
    "\n",
    "print(\"a = \", a)\n",
    "print(\"len =\", len(a))\n",
    "print(\"min =\", min(a))\n",
    "print(\"max =\", max(a))\n",
    "print(\"sum =\", sum(a))"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 比较两个列表"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在比较两个列表之前，我们需要提及一些有趣的事实。我们见到的许多东西它们都是 Python 对象。\n",
    "\n",
    "Python 对象会包含三个部分:\n",
    "- 值，我们可以通过类似 `print()` 看到它的内容；\n",
    "- 类型，我们可以通过 `type()` 来确定对象的类型；\n",
    "- id, 它代表对象在计算机中的物理编号，可以通过 `id()` 查看。\n",
    "\n",
    "如果我们想比较两个 Python 对象的内容是否相同，我们比较的是**它们的值**，主要使用 `==`\n",
    "\n",
    "如果我们想比较两个 Python 对象是否是同一个对象，我们比较的是**它们的 id**，主要使用 `is`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "a: [10, 20, 30]\n",
      "b: [10, 20, 30]\n",
      "c: [10, 20, 30]\n",
      "d: [10, 20, 33]\n",
      "\n",
      "id(a): 2101264423296\n",
      "id(b): 2101264423296\n",
      "id(c): 2101264422272\n",
      "id(d): 2101264421952\n",
      "\n",
      "a == b: True\n",
      "a == c: True\n",
      "a == d: False\n",
      "\n",
      "a is b: True\n",
      "a is c: False\n",
      "a is d: False\n",
      "\n",
      "a != b: False\n",
      "a != c: False\n",
      "a != d: True\n",
      "\n",
      "a is not b: False\n",
      "a is not c: True\n",
      "a is not d: True\n"
     ]
    }
   ],
   "source": [
    "# Create some lists\n",
    "a = [10, 20, 30]\n",
    "b = a\n",
    "c = [10, 20, 30] # Is c the same as a and b??\n",
    "d = [10, 20, 33] # d is totally different\n",
    "\n",
    "print(\"a:\", a)\n",
    "print(\"b:\", b)\n",
    "print(\"c:\", c)\n",
    "print(\"d:\", d)\n",
    "print()\n",
    "\n",
    "# Variable names a and b both point to the exact same list object\n",
    "# We can confirm this by printing the id for each variable name\n",
    "print(\"id(a):\", id(a))\n",
    "print(\"id(b):\", id(b))\n",
    "print(\"id(c):\", id(c))\n",
    "print(\"id(d):\", id(d))\n",
    "print()\n",
    "\n",
    "# c is a list that has the same contents as a (and b) but is actually a\n",
    "# different object\n",
    "\n",
    "# Use the visualize button to help see this difference in pythontutor\n",
    "\n",
    "# Operator list1 == list2 checks to see if the two objects are \n",
    "# \"equal\", specifically:\n",
    "# 1) both objects are lists\n",
    "# 2) both lists have the same length\n",
    "# 3) the corresponding elements in each list are equal\n",
    "\n",
    "# Operator list1 is list2 checks to see if the two objects are \n",
    "# actually the same object, specifically: both objects have the same id\n",
    "\n",
    "print(\"a == b:\", (a == b))\n",
    "print(\"a == c:\", (a == c))\n",
    "print(\"a == d:\", (a == d))\n",
    "print()\n",
    "print(\"a is b:\", (a is b))\n",
    "print(\"a is c:\", (a is c))\n",
    "print(\"a is d:\", (a is d))\n",
    "print()\n",
    "print(\"a != b:\", (a != b))\n",
    "print(\"a != c:\", (a != c))\n",
    "print(\"a != d:\", (a != d))\n",
    "print()\n",
    "print(\"a is not b:\", (a is not b))\n",
    "print(\"a is not c:\", (a is not c))\n",
    "print(\"a is not d:\", (a is not d))"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 通过索引和切片访问元素"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "a        = [2, 3, 5, 7, 11, 13]\n",
      "a[0]     = 2\n",
      "a[2]     = 5\n",
      "a[-1]    = 13\n",
      "a[-3]    = 7\n",
      "a[0:2]   = [2, 3]\n",
      "a[1:4]   = [3, 5, 7]\n",
      "a[1:6:2] = [3, 7, 13]\n"
     ]
    }
   ],
   "source": [
    "# Indexing and slicing for lists works the same way as it did for strings!\n",
    "\n",
    "a = [2, 3, 5, 7, 11, 13]\n",
    "print(\"a        =\", a)\n",
    "\n",
    "# Access non-negative indexes\n",
    "print(\"a[0]     =\", a[0])\n",
    "print(\"a[2]     =\", a[2])\n",
    "\n",
    "# Access negative indexes\n",
    "print(\"a[-1]    =\", a[-1])\n",
    "print(\"a[-3]    =\", a[-3])\n",
    "\n",
    "# Access slices a[start:end:step]\n",
    "print(\"a[0:2]   =\", a[0:2])\n",
    "print(\"a[1:4]   =\", a[1:4])\n",
    "print(\"a[1:6:2] =\", a[1:6:2])"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 修改列表"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2101263364224\n",
      "['G', 'A', 'T', 'T', 'A', 'C', 'A']\n",
      "['C', 'A', 'T', 'T', 'A', 'C', 'A']\n",
      "['C', 'A', 'T', 'G', 'A', 'C', 'A']\n",
      "['C', 'A', 'T', 'G', 'A', 'G', 'A']\n",
      "2101263364224\n"
     ]
    }
   ],
   "source": [
    "dna = ['G', 'A', 'T', 'T', 'A', 'C', 'A']\n",
    "print(id(dna))\n",
    "print(dna)\n",
    "\n",
    "dna[0] = 'C'\n",
    "print(dna)\n",
    "dna[3] = 'G'\n",
    "print(dna)\n",
    "dna[-2] = 'G'\n",
    "print(dna)\n",
    "print(id(dna))\n",
    "# Note the object id stayed the same. We \"mutated\" the list object rather than\n",
    "# making new list objects"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "另一种让序列“突变”的方法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2101263822336\n",
      "[10, 20, 30, 20]\n",
      "[10, 20, 30, 20, 10]\n",
      "[10, 20, 25, 30, 20, 10]\n",
      "[10, 20, 25, 30, 20]\n",
      "[10, 20, 25, 20]\n",
      "[10, 25, 20]\n",
      "2101263822336\n"
     ]
    }
   ],
   "source": [
    "a = [10, 20, 30, 20]\n",
    "print(id(a))\n",
    "print(a)\n",
    "\n",
    "a.append(10) # Add element to the end\n",
    "print(a)\n",
    "\n",
    "a.insert(2, 25) # Insert 25 into index 2 (bumping others to the right)\n",
    "print(a)\n",
    "\n",
    "a.pop() # Remove element from the end\n",
    "print(a)\n",
    "\n",
    "a.pop(3) # Remove element at index 3\n",
    "print(a)\n",
    "\n",
    "a.remove(20) # Remove (first occurrence of) element with value 20\n",
    "print(a)\n",
    "print(id(a)) # Same id as before we did any of these mutations\n",
    "\n",
    "# Append, insert, pop and remove are all examples of \"destructive\" methods, i.e.\n",
    "# methods that change the contents of the list *without* creating a new list"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 可变列表与它的别名"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Unlike strings, lists are mutable. This means that they can be changed, without creating a new list.\n",
    "This also forces us to better understand aliases, when two variables reference the same value. Aliases are only interesting (and challenging) for mutable values like lists.\n",
    "Note: it will be especially helpful to use the Visualize feature in the following examples.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Example:\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Create a list\n",
    "a = [ 2, 3, 5, 7 ]\n",
    "\n",
    "# Create an alias to the list\n",
    "b = a\n",
    "\n",
    "# We now have two references (aliases) to the SAME list\n",
    "a[0] = 42\n",
    "b[1] = 99\n",
    "print(a)\n",
    "print(b)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Function Parameters are Aliases:\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def f(a):\n",
    "    a[0] = 42\n",
    "a = [2, 3, 5, 7]\n",
    "f(a)\n",
    "print(a)\n",
    "\n",
    "# Note that the parameter alias can still be broken by re-assigning the variable\n",
    "\n",
    "a = [3, 2, 1]\n",
    "\n",
    "def foo(a):\n",
    "     a[0] = 1\n",
    "     a = [5, 2, 0] # we break the alias here!\n",
    "     a[0] = 4\n",
    "\n",
    "foo(a)\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Another Example:\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Create a list\n",
    "a = [ 2, 3, 5, 7 ]\n",
    "\n",
    "# Create an alias to the list\n",
    "b = a\n",
    "\n",
    "# Create a different list with the same elements\n",
    "c = [ 2, 3, 5, 7 ]\n",
    "\n",
    "# a and b are references (aliases) to the SAME list\n",
    "# c is a reference to a different but EQUAL list\n",
    "\n",
    "print(\"initially:\")\n",
    "print(\"  a==b  :\", a==b)\n",
    "print(\"  a==c  :\", a==c)\n",
    "print(\"  a is b:\", a is b) # the is operation tells if two values are aliases\n",
    "print(\"  a is c:\", a is c)\n",
    "\n",
    "# Now changes to a also change b (the SAME list) but not c (a different list)\n",
    "a[0] = 42\n",
    "print(\"After changing a[0] to 42\")\n",
    "print(\"  a=\", a)\n",
    "print(\"  b=\", b)\n",
    "print(\"  c=\", c)\n",
    "print(\"  a==b  :\", a==b)\n",
    "print(\"  a==c  :\", a==c)\n",
    "print(\"  a is b:\", a is b)\n",
    "print(\"  a is c:\", a is c)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Copying Lists [Pre-reading]\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Copy vs Alias\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Because of aliasing, we have to be careful if we share a reference\n",
    "# to a list in the same way we might for number or a string,\n",
    "# by simply setting b = a, like so:\n",
    "\n",
    "import copy\n",
    "\n",
    "# Create a list\n",
    "a = [ 2, 3 ]\n",
    "\n",
    "# Try to copy it\n",
    "b = a             # Error!  Not a copy, but an alias\n",
    "c = copy.copy(a)  # Ok\n",
    "\n",
    "# At first, things seem ok\n",
    "print(\"At first...\")\n",
    "print(\"   a =\", a)\n",
    "print(\"   b =\", b)\n",
    "print(\"   c =\", c)\n",
    "\n",
    "# Now modify a[0]\n",
    "a[0] = 42\n",
    "print(\"But after a[0] = 42\")\n",
    "print(\"   a =\", a)\n",
    "print(\"   b =\", b)\n",
    "print(\"   c =\", c)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Other ways to copy\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import copy\n",
    "\n",
    "a = [2, 3]\n",
    "\n",
    "b = copy.copy(a)\n",
    "c = a[:]\n",
    "d = a + [ ]\n",
    "e = list(a)\n",
    "\n",
    "a[0] = 42\n",
    "print(a, b, c, d, e)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Destructive and Non-destructive Functions\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Because lists are mutable, we can change them in two ways:\n",
    "destructively (which modifies the original value directly), and\n",
    "non-destructively (which creates a new list and does not modify the original value).\n",
    "This also affects how we write functions that use lists."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Destructive functions\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# A destructive function is written to directly change the provided list\n",
    "# It does not need to return anything, as the caller can access the original list\n",
    "def fill(a, value):\n",
    "    for i in range(len(a)):\n",
    "        a[i] = value\n",
    "\n",
    "a = [1, 2, 3, 4, 5]\n",
    "print(\"At first, a =\", a)\n",
    "fill(a, 42)\n",
    "print(\"After fill(a, 42), a =\", a)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Non-destructive function\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import copy\n",
    "\n",
    "## First, a quick primer on modifying lists ##\n",
    "## We'll talk about these more in a bit ##\n",
    "\n",
    "a = [1, 2, 3, 4]\n",
    "\n",
    "# .remove() DESTRUCTIVELY removes the given value from the list\n",
    "a.remove(2)\n",
    "print(a) # [1, 3, 4]\n",
    "\n",
    "# .append() DESTRUCTIVELY adds the given value to the end of the list\n",
    "a.append(70)\n",
    "print(a) # [1, 3, 4, 70]\n",
    "\n",
    "## Now, on to NON-DESTRUCTIVE functions! ##\n",
    "\n",
    "def destructiveRemoveAll(a, value):\n",
    "    while (value in a):\n",
    "        a.remove(value)\n",
    "\n",
    "def nonDestructiveRemoveAll(a, value):\n",
    "    # Typically, we write non-destructive functions by building a new list\n",
    "    # instead of changing the original\n",
    "    result = []\n",
    "    for element in a:\n",
    "        if (element != value):\n",
    "            result.append(element)\n",
    "    return result # non-destructive functions still need to return!\n",
    "\n",
    "def alternateNonDestructiveRemoveAll(a, value):\n",
    "    # We can write the same function by breaking the alias,\n",
    "    # then using the destructive approach\n",
    "    a = copy.copy(a)\n",
    "    destructiveRemoveAll(a, value)\n",
    "    return a\n",
    "\n",
    "a = [ 1, 2, 3, 4, 3, 2, 1 ]\n",
    "print(\"At first\")\n",
    "print(\"   a =\", a)\n",
    "\n",
    "destructiveRemoveAll(a, 2)\n",
    "print(\"After destructiveRemoveAll(a, 2)\")\n",
    "print(\"   a =\", a)\n",
    "\n",
    "b = nonDestructiveRemoveAll(a, 3)\n",
    "print(\"After b = nonDestructiveRemoveAll(a, 3)\")\n",
    "print(\"   a =\", a)\n",
    "print(\"   b =\", b)\n",
    "\n",
    "c = alternateNonDestructiveRemoveAll(a, 1)\n",
    "print(\"After c = alternateNonDestructiveRemoveAll(a, 1)\")\n",
    "print(\"   a =\", a)\n",
    "print(\"   c =\", c)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Finding Elements\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Check for list membership: in\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = [ 2, 3, 5, 2, 6, 2, 2, 7 ]\n",
    "print(\"a      =\", a)\n",
    "print(\"2 in a =\", (2 in a))\n",
    "print(\"4 in a =\", (4 in a))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Check for list non-membership: not in"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = [ 2, 3, 5, 2, 6, 2, 2, 7 ]\n",
    "print(\"a          =\", a)\n",
    "print(\"2 not in a =\", (2 not in a))\n",
    "print(\"4 not in a =\", (4 not in a))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Count occurrences in list: list.count(item)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = [ 2, 3, 5, 2, 6, 2, 2, 7 ]\n",
    "print(\"a          =\", a)\n",
    "print(\"a.count(1) =\", a.count(1))\n",
    "print(\"a.count(2) =\", a.count(2))\n",
    "print(\"a.count(3) =\", a.count(3))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Find index of item: list.index(item) and list.index(item, start)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Example\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = [ 2, 3, 5, 2, 6, 2, 2, 7 ]\n",
    "print(\"a            =\", a)\n",
    "print(\"a.index(6)   =\", a.index(6))\n",
    "print(\"a.index(2)   =\", a.index(2))\n",
    "print(\"a.index(2,1) =\", a.index(2,1))\n",
    "print(\"a.index(2,4) =\", a.index(2,4))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Problem: crashes when item is not in list\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = [ 2, 3, 5, 2 ]\n",
    "print(\"a          =\", a)\n",
    "print(\"a.index(9) =\", a.index(9)) # crashes!\n",
    "print(\"This line will not run!\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Solution: use (item in list)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = [ 2, 3, 5, 2 ]\n",
    "print(\"a =\", a)\n",
    "if (9 in a):\n",
    "    print(\"a.index(9) =\", a.index(9))\n",
    "else:\n",
    "    print(\"9 not in\", a)\n",
    "print(\"This line will run now!\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Adding Elements\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Destructively (Modifying Lists)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Add an item with list.append(item)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = [ 2, 3 ]\n",
    "a.append(7)\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Add a list of items with list += list2 or list.extend(list2)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = [ 2, 3 ]\n",
    "a += [ 11, 13 ]\n",
    "print(a)\n",
    "a.extend([ 17, 19 ])\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Insert an item at a given index\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = [ 2, 3, 5, 7, 11 ]\n",
    "a.insert(2, 42)  # at index 2, insert 42\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Non-Destructively (Creating New Lists)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Add an item with list1 + list2\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = [ 2, 3 ]\n",
    "b = a + [ 13, 17 ]\n",
    "print(a)\n",
    "print(b)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Insert an item at a given index (with list slices)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = [ 2, 3 ]\n",
    "b = a[:2] + [5] + a[2:]\n",
    "print(a)\n",
    "print(b)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Destructive vs Non-Destructive Example\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(\"Destructive:\")\n",
    "a = [ 2, 3 ]\n",
    "b = a\n",
    "a += [ 4 ]\n",
    "print(a)\n",
    "print(b)\n",
    "\n",
    "print(\"Non-Destructive:\")\n",
    "a = [ 2, 3 ]\n",
    "b = a\n",
    "a = a + [ 4 ] # this overwrites a, but not the alias of b\n",
    "print(a)\n",
    "print(b)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Removing Elements\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Destructively (Modifying Lists)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Remove an item with list.remove(item)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = [ 2, 3, 5, 3, 7, 6, 5, 11, 13 ]\n",
    "print(\"a =\", a)\n",
    "\n",
    "a.remove(5)\n",
    "print(\"After a.remove(5), a=\", a)\n",
    "\n",
    "a.remove(5)\n",
    "print(\"After another a.remove(5), a=\", a)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Remove an item at a given index with list.pop(index)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = [ 2, 3, 4, 5, 6, 7, 8 ]\n",
    "print(\"a =\", a)\n",
    "\n",
    "item = a.pop(3)\n",
    "print(\"After item = a.pop(3)\")\n",
    "print(\"   item =\", item)\n",
    "print(\"   a =\", a)\n",
    "\n",
    "item = a.pop(3)\n",
    "print(\"After another item = a.pop(3)\")\n",
    "print(\"   item =\", item)\n",
    "print(\"   a =\", a)\n",
    "\n",
    "# Remove last item with list.pop()\n",
    "item = a.pop()\n",
    "print(\"After item = a.pop()\")\n",
    "print(\"   item =\", item)\n",
    "print(\"   a =\", a)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Non-Destructively (Creating New Lists)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Remove an item at a given index (with list slices)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "a = [2, 3, 5, 3, 7, 5, 11, 13]\n",
      "After b = a[:2] + a[3:]\n",
      "      a = [2, 3, 5, 3, 7, 5, 11, 13]\n",
      "      b = [2, 3, 3, 7, 5, 11, 13]\n"
     ]
    }
   ],
   "source": [
    "a = [ 2, 3, 5, 3, 7, 5, 11, 13 ]\n",
    "print(\"a =\", a)\n",
    "\n",
    "b = a[:2] + a[3:]\n",
    "print(\"After b = a[:2] + a[3:]\")\n",
    "print(\"      a =\", a)\n",
    "print(\"      b =\", b)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Looping Over Lists\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Looping with a normal for loop:\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = [ 2, 3, 5, 7 ]\n",
    "print(\"Here are the items in a with their indexes:\")\n",
    "for index in range(len(a)):\n",
    "    print(\"a[\", index, \"] =\", a[index])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Looping with a for each loop\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Lists and strings are both iterable types.\n",
    "# This means that we can iterate (loop) over them directly!\n",
    "a = [ 2, 3, 5, 7 ]\n",
    "print(\"Here are the items in a:\")\n",
    "for item in a:\n",
    "    print(item)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Hazard: modifying inside a for loop\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# IMPORTANT: don't change a list inside a for loop! The indexes will behave unpredictably.\n",
    "# This isn't a problem for strings because they aren't mutable.\n",
    "a = [ 2, 3, 5, 3, 7 ]\n",
    "print(\"a =\", a)\n",
    "\n",
    "# Failed attempt to remove all the 3's\n",
    "for index in range(len(a)):\n",
    "    if (a[index] == 3):  # this eventually crashes!\n",
    "        a.pop(index)\n",
    "\n",
    "print(\"This line will not run!\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Also Hazard: modifying inside a for-each loop\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# If we remove items in a for-each loop, the loop won't crash,\n",
    "# but it won't behave as we would expect either!\n",
    "\n",
    "a = [3, 3, 2, 3, 4]\n",
    "for item in a:       # this won't reach every item in the list!\n",
    "    if (item == 3):\n",
    "      a.remove(item)\n",
    "print(a) # should be [2, 4], but there's still a 3 in there!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Better: modifying inside a while loop\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Modify the list in a while loop instead of a for loop,\n",
    "# to control how indexes \n",
    "\n",
    "a = [ 2, 3, 5, 3, 7 ]\n",
    "print(\"a =\", a)\n",
    "\n",
    "# Successful attempt to remove all the 3's\n",
    "index = 0\n",
    "while (index < len(a)):\n",
    "    if (a[index] == 3):\n",
    "        a.pop(index)\n",
    "    else:\n",
    "        index += 1\n",
    "\n",
    "print(\"This line will run!\")\n",
    "print(\"And now a =\", a)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# List Methods: Sorting and Reversing\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Lists have many built-in methods. It's common for these methods to be implemented both destructively and non-destructively.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Destructively with list.sort() or list.reverse()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = [ 7, 2, 5, 3, 5, 11, 7 ]\n",
    "print(\"At first, a =\", a)\n",
    "a.sort()\n",
    "print(\"After a.sort(), a =\",a)\n",
    "\n",
    "a = [ 2, 3, 5, 7 ]\n",
    "print(\"Here are the items in reverse:\")\n",
    "a.reverse()\n",
    "for item in a:\n",
    "    print(item)\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Non-Destructively with sorted(list) and reversed(list)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = [ 7, 2, 5, 3, 5, 11, 7 ]\n",
    "print(\"At first\")\n",
    "print(\"   a =\", a)\n",
    "b = sorted(a)\n",
    "print(\"After b = sorted(a)\")\n",
    "print(\"   a =\", a)\n",
    "print(\"   b =\", b)\n",
    "\n",
    "a = [ 2, 3, 5, 7 ]\n",
    "print(\"Here are the items in reverse:\")\n",
    "for item in reversed(a):\n",
    "    print(item)\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "More list methods\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "For most list methods, see this table and this list of list methods.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Summary: Destructive and Non-destructive\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Some destructive vs. non-destructive list analogs, for:\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = ['cat','dog','pig','cow']\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "cell_style": "split"
   },
   "source": [
    "Destructive (aliasing)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "cell_style": "center"
   },
   "outputs": [],
   "source": [
    "b = a"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 待补充"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Tuples (Immutable Lists)\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Tuples are exactly like lists, except they are immutable. We cannot change the values of a tuple.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Tuple syntax\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "t = (1, 2, 3)\n",
    "print(type(t), len(t), t)\n",
    "\n",
    "a = [1, 2, 3]\n",
    "t = tuple(a)\n",
    "print(type(t), len(t), t)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Tuples are immutable\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "t = (1, 2, 3)\n",
    "print(t[0])\n",
    "\n",
    "t[0] = 42    # crash!\n",
    "print(t[0])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Parallel (tuple) assignment\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'int'> 210\n",
      "<class 'tuple'> (42, 42, 42, 42, 42)\n"
     ]
    }
   ],
   "source": [
    "(x, y) = (1, 2)\n",
    "print(x)\n",
    "print(y)\n",
    "\n",
    "# tuples are useful for swapping!\n",
    "(x, y) = (y, x)\n",
    "print(x)\n",
    "print(y)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Singleton tuple syntax\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "t = (42)\n",
    "print(type(t), t*5)\n",
    "\n",
    "t = (42,) # use a comma to force the type\n",
    "print(type(t), t*5)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# List Comprehensions\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "List comprehensions are a handy way to create lists using simple loops all in one line.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Long way\n",
    "a = []\n",
    "for i in range(10):\n",
    "    a.append(i)\n",
    "print(a)\n",
    "\n",
    "# Short way\n",
    "a = [i for i in range(10)]\n",
    "print(a)\n",
    "\n",
    "# We can also add conditionals at the end (but keep it simple!)\n",
    "a = [(i*100) for i in range(20) if i%5 == 0]\n",
    "print(a)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Converting Between Lists and Strings\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# use list(s) to convert a string to a list of characters\n",
    "a = list(\"wahoo!\")\n",
    "print(a)  # prints: ['w', 'a', 'h', 'o', 'o', '!']\n",
    "\n",
    "# use s1.split(s2) to convert a string to a list of strings delimited by s2\n",
    "a = \"How are you doing today?\".split(\" \")\n",
    "print(a) # prints ['How', 'are', 'you', 'doing', 'today?']\n",
    "\n",
    "# use \"\".join(a) to convert a list of characters to a single string\n",
    "print(\"\".join(a))  # prints: Howareyoudoingtoday?\n",
    "\n",
    "# \"\".join(a) also works on a list of strings (not just single characters)\n",
    "a = [\"parsley\", \"is\", \"gharsley\"] # by Ogden Nash!\n",
    "print(\"\".join(a))  # prints: parsleyisgharsley\n",
    "print(\" \".join(a)) # prints: parsley is gharsley"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Worked Examples Using Lists\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If you want to review more examples of problem-solving with lists, you can find several worked examples here. We'll go over some of these in class as well.\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.15"
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
